/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.eurotrader.dao;

import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 *
 * @author Anjo
 */
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class BaseDaoImp<T, ID> implements BaseDao<T, ID> {

    @PersistenceContext(unitName = "PlataformaPU")
    private EntityManager entityManager;
    private Class<T> persistentClass;
    private static Logger log;
//    @Resource
//    private UserTransaction userTransaction;

    public BaseDaoImp() {
        log = Logger.getLogger(this.getClass().getName());
        this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

    }

    public Class<T> getPersistentClass() {
        return persistentClass;
    }

    public EntityManager getEntityManager() {
        return entityManager;
    }

    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Override
    public T save(T entidade) {
        //getEntityManager().getTransaction().begin();
        try {
            //userTransaction.begin();

            getEntityManager().persist(entidade);

            //userTransaction.commit();
        } catch (Exception ex) {
            Logger.getLogger(BaseDaoImp.class.getName()).log(Level.SEVERE, null, ex);
        }
        // getEntityManager().getTransaction().commit();
        return (T) entidade;
    }

    public T getByID(ID id) {
        T entidade = (T) getEntityManager().find(getPersistentClass(), id);
        return entidade;
    }

    public void delete(T entidade) {
        try {
            //userTransaction.begin();
            if (!getEntityManager().contains(entidade)) {
                entidade = getEntityManager().merge(entidade);
            }
            getEntityManager().remove(entidade);
            // userTransaction.commit();
        } catch (Exception ex) {
            Logger.getLogger(BaseDaoImp.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void update(T entidade) {
        try {
            //userTransaction.begin();

            getEntityManager().merge(entidade);
            // userTransaction.commit();
        } catch (Exception ex) {
            Logger.getLogger(BaseDaoImp.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public List<T> getAll() {
        Query query;
        String queryS;
        queryS = "SELECT obj FROM " + persistentClass.getSimpleName() + " obj";
        query = getEntityManager().createQuery(queryS);
        return query.getResultList();
    }

    @Override
    public List pesq(String query, String ordenacao) {
        try {
            if (entityManager.isOpen()) {
                return getEntityManager().createQuery(query + " " + ordenacao).getResultList();
            } else {
                return null;
            }
        } catch (javax.persistence.NoResultException e) {
            return null;
        }
    }

    public T getResultadoSimples(String query) {
        try {
            return (T) getEntityManager().createQuery(query).getSingleResult();
        } catch (javax.persistence.NoResultException e) {
            return null;
        }
    }

    public Object getResultSimples(String query) {
        Object obj = null;
        try {
            obj = getEntityManager().createQuery(query).getSingleResult();
        } catch (javax.persistence.NoResultException e) {
            return null;
        } catch (javax.persistence.NonUniqueResultException e) {
            return obj;
        }
        return obj;
    }

    public Boolean encontrouRegistro(String query) {
        Object objeto;
        try {
            objeto = getEntityManager().createQuery(query).getSingleResult();
        } catch (javax.persistence.NoResultException e) {
            return false;
        } catch (javax.persistence.NonUniqueResultException e) {
            return true;
        }
        return true;
    }

    public List<T> getByField(String campo, String texto) {
        List lista;
        lista = getEntityManager().createQuery("SELECT p FROM " + persistentClass.getSimpleName()
                + " p  WHERE p." + campo + " LIKE '" + texto + "%' ORDER BY p.id DESC").getResultList();
        return lista;

    }

    public Object getPorCampo(String campo, String texto) {
        try {
            return getEntityManager().createQuery("SELECT p FROM " + persistentClass.getSimpleName()
                    + " p  WHERE p." + campo + " = '" + texto + "'").getSingleResult();
        } catch (javax.persistence.NoResultException e) {
            return null;
        }

    }

    public List<T> listPesqParam(String query, Map<String, Object> params, int maximo, int atual) {
        Query q = getEntityManager().createQuery(query).setMaxResults(maximo).setFirstResult(atual);

        for (String chave : params.keySet()) {
            q.setParameter(chave, params.get(chave));
        }
        return q.getResultList();
    }

    public List<T> listPesqParam(String query, Map<String, Object> params) {
        Query q = getEntityManager().createQuery(query);

        for (String chave : params.keySet()) {
            q.setParameter(chave, params.get(chave));
        }
        return q.getResultList();
    }

    public T listPesqParamSimples(String query, Map<String, Object> params) {
        try {
            Query q = getEntityManager().createQuery(query);
            System.out.println("query..."+q);
            System.out.println("----::");
            for (String chave : params.keySet()) {
                System.out.println("----::"+chave);
                System.out.println("---- get ::"+params.get(chave));
                q.setParameter(chave, params.get(chave));
            }
            return (T) q.getSingleResult();
        } catch (javax.persistence.NoResultException e) {
            System.out.println("nada de achar");
            return null;
        }
    }

    public Long getTotalDeRegistros() {
        return (Long) getEntityManager().createQuery("SELECT COUNT(c) FROM " + persistentClass.getSimpleName() + " c").getSingleResult();
    }

    public Long getTotalDeRegistros(String sql) {
        return (Long) getEntityManager().createQuery("SELECT COUNT(c) FROM " + persistentClass.getSimpleName() + " c " + sql).getSingleResult();
    }

    public List todosRegistrosPaginados(int maximo, int atual) {
        return getEntityManager().createQuery("SELECT c FROM " + persistentClass.getSimpleName() + " c ORDER BY c.id DESC").setFirstResult(atual).setMaxResults(maximo).getResultList();
    }
    
    public List ultimosRegistros(int maximo, String clausulaSql) {
        return getEntityManager().createQuery("SELECT c FROM " + persistentClass.getSimpleName() + " c " + clausulaSql).setMaxResults(maximo).getResultList();
    }

    public List todosRegistrosPag(int maximo, int atual, String sql) {
        if (sql.toUpperCase().contains("ORDER BY")){
            return getEntityManager().createQuery(sql).setFirstResult(atual).setMaxResults(maximo).getResultList();
        }else{
            return getEntityManager().createQuery(sql + " ORDER BY c.id DESC").setFirstResult(atual).setMaxResults(maximo).getResultList();
        }
        //  getEntityManager().close();
    }

    public void excluiTodos(String sql) {
        Query q = entityManager.createQuery("delete from " + persistentClass.getSimpleName() + " " + sql);
        q.executeUpdate();

    }

    public Long numeroDeRegistros(String sql) {
        return (Long) getEntityManager().createQuery(sql).getSingleResult();
    }

    public Object getPrimeiroResultado(String query, String ordenacao) {
        Object obj = null;
        try {
            obj = getEntityManager().createQuery(query + " " + ordenacao).setMaxResults(1).getSingleResult();
        } catch (javax.persistence.NoResultException e) {
            return null;
        } catch (javax.persistence.NonUniqueResultException e) {
            return obj;
        }
        return obj;
    }
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
